import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.Random;

public class Game2048 extends JPanel{
    private static final int SIZE=4;
    private  static final  int SQUARE_A=100;
    private int[][] grid=new int[SIZE][SIZE];
    private final Random random = new Random();
    private boolean win=false;
    private boolean lose=false;


Game2048(){
    setFocusable(true);
    addKeyListener(new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            super.keyPressed(e);
            if(!win&&!lose){
                switch (e.getKeyCode()){
                    case KeyEvent.VK_LEFT -> moveLeft();
                    case KeyEvent.VK_RIGHT -> moveRight();
                    case KeyEvent.VK_UP -> moveUp();
                    case KeyEvent.VK_DOWN -> moveDown();
                }
            }

            repaint();
            spawnTile();
            checkGameState();
        }
    });
    spawnTile();
    spawnTile();
}
private void moveLeft() {
    for (int row = 0; row < SIZE; row++) {
        int[] mergedRow = new int[SIZE];
        Arrays.fill(mergedRow, 0);
        boolean[] alreadMerage = new boolean[SIZE];
        int colIndex = 0;//指示的是该行合并结果的第几个
        for (int col = 0; col < SIZE; col++) {
            if (grid[row][col] != 0) {
                if (colIndex == 0) {
                    mergedRow[colIndex] = grid[row][col];
                    colIndex++;
                } else {
                    if (grid[row][col] == mergedRow[colIndex - 1]
                            && !alreadMerage[colIndex - 1]) {//合并
                        mergedRow[colIndex - 1] *= 2;
                    } else {
                        mergedRow[colIndex] = grid[row][col];
                        colIndex++;
                    }
                }
            }
        }
        System.arraycopy(mergedRow,0,grid[row],0,SIZE);
    }
}

     private void moveUp(){
    //转270°
         rotateRight();
         rotateRight();
         rotateRight();
         moveLeft();
         //转180°
         rotateRight();
         rotateRight();

    }
    private void moveRight(){
    //转180°
        rotateRight();
        rotateRight();
        moveLeft();
        //转180°
        rotateRight();
        rotateRight();
    }
    private void moveDown(){
    //转90
        rotateRight();
        moveLeft();
        //转270°
        rotateRight();
        rotateRight();
        rotateRight();
    }

    private void checkGameState() {
    int cnt=0;
        for (int row = 0; row < SIZE; row++) {
            for(int col=0;col<SIZE;col++){
                if(grid[row][col]==2048){
                    win=true;
                    break;
                }else{
                    if(grid[row][col]!=0){}
                    cnt++;
                }
            }
            if(win){
                break;
            }
        }
        if(!win){
            if(cnt<SIZE*SIZE){
                return;
            }
            for(int row=0;row<SIZE;row++){
                for(int col=0;col<SIZE;col++){
                    if(row<SIZE-1&&grid[row][col]==grid[row+1][col]){
                        return;
                    }
                    if(col<SIZE-1&&grid[row][col]==grid[row][col+1]){
                        return;
                    }
                }
            }
            lose=true;
        }
    }

    private void rotateRight(){
    int[][]newGrid= new int[SIZE][SIZE];
    for(int row=0;row<SIZE;row++){
        for(int col=0;col<SIZE;col++){
            newGrid[col][SIZE-row-1]=grid[row][col];
        }
    }
    grid=newGrid;
    }

    private void spawnTile(){
    int cnt=0;
    for(int row=0;row<SIZE;row++){
        for(int col=0;col<SIZE;col++){
            if (grid[row][col]!=0){
                cnt++;
            }
            }
        }
    if (cnt==SIZE*SIZE){
        return;}


    int x,y;
     do{
         x=random.nextInt(SIZE);
         y=random.nextInt(SIZE);

     }while (grid[x][y]!=0);
         grid[x][y]=random.nextInt(10)<5?2:4;
}


    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.LIGHT_GRAY);
        g.fillRect(0, 0, getWidth(), getHeight());
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                //画小格子
                drawTile(g, grid[i][j], j * 100, i * 100);


            }
        }
        g.setColor(Color.GREEN);
        if (win) {
            g.drawString("You Win!", getWidth() / 2, getHeight() / 2);
        }
        if (lose) {
            g.drawString("Game Over!", getWidth() / 2, getHeight() / 2);
        }
    }
    //g画笔，value：格子上的数字，x，y为格子的坐标
    private  void drawTile(Graphics g,int value, int x,int y){
        int r=(int)(Math.log(value)/Math.log(2));
        g.setColor(value==0?Color.GRAY:new Color(255-r*20,240,200));
        g.fillRect(x,y,100,100);
        g.setColor(Color.BLACK);
        g.drawRect(x,y,100,100);

        if(value !=0){
            String text =String.valueOf(value);
            FontMetrics fm=g.getFontMetrics();
            int w=fm.stringWidth(text);
            int h=fm.getHeight();
            int textX=x+(100-w)/2;
            int textY=y+(100-h)/2+fm.getAscent();
            g.drawString(text,textX,textY);

        }
    }

    public static void main(String[] args){
        JFrame frame = new JFrame("2048 Game");
        frame.setSize(420,460);
        Game2048 game2048= new Game2048();
        frame.add(game2048);
        frame.setVisible(true);
    }

}